//
// Source status recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.weixing.oauth2.common.provider.token;

import com.google.common.collect.Lists;
import com.weixing.oauth2.common.userdetails.IUserDetailsService;
import com.weixing.oauth2.common.userdetails.SecurityUser;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.oauth2.provider.token.UserAuthenticationConverter;
import org.springframework.util.StringUtils;

import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;

public class CustomUserAuthenticationConverter implements UserAuthenticationConverter {
    private Collection<? extends GrantedAuthority> defaultAuthorities;
    private IUserDetailsService userDetailsService;

    public CustomUserAuthenticationConverter() {
    }

    public void setUserDetailsService(IUserDetailsService userDetailsService) {
        this.userDetailsService = userDetailsService;
    }

    public void setDefaultAuthorities(String[] defaultAuthorities) {
        this.defaultAuthorities = AuthorityUtils.commaSeparatedStringToAuthorityList(StringUtils.arrayToCommaDelimitedString(defaultAuthorities));
    }

    @Override
    public Map<String, ?> convertUserAuthentication(Authentication authentication) {
        Map<String, Object> response = new LinkedHashMap();
        response.put("user_name", authentication.getName());
        if (authentication.getAuthorities() != null && !authentication.getAuthorities().isEmpty()) {
            response.put("authorities", AuthorityUtils.authorityListToSet(authentication.getAuthorities()));
        }
        return response;
    }
    @Override
    public Authentication extractAuthentication(Map<String, ?> map) {
        if (map.containsKey("user_name")) {
            Object principal = map.get("user_name");
            Collection<? extends GrantedAuthority> authorities = Lists.newArrayList();

            /**
             * 此处加载登录用户的认证信息
             * 1、可以从数据库中查询，这种方法效率不高，因为每次都要去查数据库
             * 2、可以在用户登录的时候将用户认证信息存放在redis等缓存中，从缓存中取
             * 3、如果是jwt的话，可以在用户登录成功后将权限信息存放在token中，从token中直接解析权限
             * 此处采用的是第三种做法
             */
            String userName = (String) map.get("user_name");
//            authorities = userDetailsService.loadAuthority(userId);
            UserDetails user = new SecurityUser(authorities,userName);
            principal = user;
            return new UsernamePasswordAuthenticationToken(principal, "N/A", authorities);
        } else {
            return null;
        }
    }

    private Collection<? extends GrantedAuthority> getAuthorities(Map<String, ?> map) {
        if (!map.containsKey("authorities")) {
            return this.defaultAuthorities;
        } else {
            Object authorities = map.get("authorities");
            if (authorities instanceof String) {
                // 解密
                return AuthorityUtils.commaSeparatedStringToAuthorityList((String)authorities);
            } else if (authorities instanceof Collection) {
                return AuthorityUtils.commaSeparatedStringToAuthorityList(StringUtils.collectionToCommaDelimitedString((Collection)authorities));
            } else {
                throw new IllegalArgumentException("Authorities must be either a String or a Collection");
            }
        }
    }


    public static void main(String[] args) throws Exception {
    }
}
